#include <syslog.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <limits.h>
#include "tag_generator.h"

// TAG structure:
/*********************///---------------------
/**                 **/
/**      HEAD       **/
/**                 **/
/*********************/
/**                 **/
/**     ITERM1      **/
/**                 **/
/*********************///        32K
/**                 **/
/**     ITERM2      **/
/**                 **/
/*********************/
/**                 **/
/**      ...        **/
/**                 **/
/*********************///---------------------
/**                 **/
/**   ITERM1_BAK    **/
/**                 **/
/*********************/
/**                 **/
/**   ITERM2_BAK    **/
/**                 **/
/*********************///        32K backup
/**                 **/
/**      ...        **/
/**                 **/
/*********************/
/**                 **/
/**      END        **/
/**                 **/
/*********************///---------------------

#define MAX_TAG_SIZE (64 * 1024)
#define HALF_TAG_SIZE (MAX_TAG_SIZE / 2)
#define SEGMENT_SIZE (4 * 1024)
#define MAX_CMDLINE_LENGTH 1024
#define MAX_HEAD_SIZE 4 /* head size for each segment */
#define TAG_HEAD						0xa108c309
#define TAG_END							0x55aacc33

#define TAG_INFO_OFFSET					0
#define TAG_INFO_SIZE					SEGMENT_SIZE /* 4K bytes */
#define ENV_OFFSET						(TAG_INFO_OFFSET + TAG_INFO_SIZE)
#define ENV_MAX_SIZE					SEGMENT_SIZE /* 4K bytes */
#define BOARDINFO_OFFSET				(ENV_OFFSET + ENV_MAX_SIZE)
#define BOARDINFO_MAX_SIZE				SEGMENT_SIZE /* 4K bytes */
#define USER0_OFFSET					(HALF_TAG_SIZE - USER0_MAX_SIZE)
#define USER0_MAX_SIZE					SEGMENT_SIZE /* the last 4K bytes */

#define TAG_SIZE						MAX_TAG_SIZE

static const char g_env_head[4] = {'E', 'N', 'V', 'I'};
static const char g_boardinfo_head[4] = {'B', 'D', 'I', 'F'};
static const char g_user0_head[4] = {'U', 'S', 'R', '0'};

static int file_create_ok(const char *path)
{
	int fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644);
	if (fd < 0) {
		printf("%s can't be create: %s\n", path, strerror(errno));
		return -1;
	}

	close(fd);

	unlink(path);
	return 0;
}

static int write_segment_to_buffer(uint8_t *to, uint8_t *from, int len)
{
	memset((void *)to, 0xff, SEGMENT_SIZE);
	memcpy((void *)to, from, len);
	return 0;
}

static int write_segment_to_file(int fd, uint32_t offset, uint8_t *from, int len)
{
	int ret;

	lseek(fd, offset, SEEK_SET);

	ret = write(fd, from, len);
	if (ret != len) {
		printf("write tag failed\n");
		return -1;
	}

	return 0;
}

int dump_tag(const char *path)
{
	int ret = 0;
	uint8_t *buf = (uint8_t *)malloc(MAX_TAG_SIZE);
	if (buf == NULL) {
		printf("malloc dump buf failed:%s\n", strerror(errno));
		return -1;
	}

	int fd = open(path, O_RDONLY);
	if (fd < 0) {
		printf("%s can't be read: %s\n", path, strerror(errno));
		ret = -1;
		goto free_buf;
	}

	printf("dump tag:\n");

	int len = read(fd, buf, MAX_TAG_SIZE);
	if (len == 0) {
		printf("empty file\n");
		ret = -1;
		goto close_file;
	}

	if (*(uint32_t *)buf != TAG_HEAD) {
		printf("Invalid tag head\n");
		ret = -1;
		goto close_file;
	}

	if (*(uint32_t *)(buf + TAG_SIZE - 4) != TAG_END) {
		printf("Invalid tag end\n");
		ret = -1;
		goto close_file;
	}

	char *env_p = (char *)(buf + ENV_OFFSET);
	uint32_t *env_head_p = (uint32_t *)&g_env_head;
	if (*(uint32_t *)env_p != *env_head_p) {
		printf("Invalid env\n");
	} else {
		printf("env: %s\n", env_p + MAX_HEAD_SIZE);
	}

	char *boardinfo_p = (char *)(buf + BOARDINFO_OFFSET);
	uint32_t *boardinfo_head_p = (uint32_t *)&g_boardinfo_head;
	if (*(uint32_t *)boardinfo_p != *boardinfo_head_p) {
		printf("Invalid boardinfo\n");
	} else {
		printf("boardinfo: %s\n", boardinfo_p + MAX_HEAD_SIZE);
	}	

	char *user0_p = (char *)(buf + USER0_OFFSET);
	uint32_t *user0_head_p = (uint32_t *)&g_user0_head;
	if (*(uint32_t *)user0_p != *user0_head_p) {
		printf("Invalid user0\n");
	} else {
		printf("user0 params: %s\n", user0_p + MAX_HEAD_SIZE);
	}

	/* dump the bakup. */
	printf("\nDump the backup info:\n");
	char *env_bak_p = (char *)(buf + ENV_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
	if (*(uint32_t *)env_bak_p != *env_head_p) {
		printf("Invalid env\n");
	} else {
		printf("env: %s\n", env_bak_p + MAX_HEAD_SIZE);
	}

	char *boardinfo_bak_p = (char *)(buf + BOARDINFO_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
	if (*(uint32_t *)boardinfo_bak_p != *boardinfo_head_p) {
		printf("Invalid boardinfo\n");
	} else {
		printf("boardinfo: %s\n", boardinfo_bak_p + MAX_HEAD_SIZE);
	}

	char *user0_bak_p = (char *)(buf + USER0_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
	if (*(uint32_t *)user0_bak_p != *user0_head_p) {
		printf("Invalid user0\n");
	} else {
		printf("user0 params: %s\n", user0_bak_p + MAX_HEAD_SIZE);
	}

close_file:
	close(fd);
free_buf:
	free(buf);
	return ret;
}

int recover_tag(const char *path)
{
	int ret = -1, repair = 0;

	uint8_t *buf = (uint8_t *)malloc(MAX_TAG_SIZE);
	if (buf == NULL) {
		printf("malloc dump buf failed:%s\n", strerror(errno));
		return -1;
	}

	int tag_fd = open(path, O_RDWR);
	if (tag_fd < 0) {
		printf("%s can't be create: %s\n", path, strerror(errno));
		ret = -1;
		goto free_buf;
	}

	int len = read(tag_fd, buf, MAX_TAG_SIZE);
	if (len == 0) {
		printf("empty file\n");
		ret = -1;
		goto close_file;
	}

	if (*(uint32_t *)buf != TAG_HEAD) {
		printf("Invalid tag head\n");
		ret = -1;
		goto close_file;
	}

	if (*(uint32_t *)(buf + TAG_SIZE - 4) != TAG_END) {
		printf("Invalid tag end\n");
		ret = -1;
		goto close_file;
	}

	char *env_p = (char *)(buf + ENV_OFFSET);
	uint32_t *env_head_p = (uint32_t *)&g_env_head;
	if (*(uint32_t *)env_p != *env_head_p) {
		printf("Invalid env, repair...\n");
		uint8_t *env_bak_p = (uint8_t *)(buf + ENV_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
		ret = write_segment_to_file(tag_fd, ENV_OFFSET, env_bak_p, SEGMENT_SIZE);
		if (ret < 0) {
			printf("failed to write env to tag file\n");
			ret = -1;
			goto close_file;
		}
		repair++;
	}

	char *boardinfo_p = (char *)(buf + BOARDINFO_OFFSET);
	uint32_t *boardinfo_head_p = (uint32_t *)&g_boardinfo_head;
	if (*(uint32_t *)boardinfo_p != *boardinfo_head_p) {
		printf("Invalid boardinfo, repair...\n");
		uint8_t *boardinfo_bak_p = (uint8_t *)(buf + BOARDINFO_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
		ret = write_segment_to_file(tag_fd, BOARDINFO_OFFSET, boardinfo_bak_p, SEGMENT_SIZE);
		if (ret < 0) {
			printf("failed to write boardinfo to tag file\n");
			ret = -1;
			goto close_file;
		}
		repair++;
	}

	char *user0_p = (char *)(buf + USER0_OFFSET);
	uint32_t *user0_head_p = (uint32_t *)&g_user0_head;
	if (*(uint32_t *)user0_p != *user0_head_p) {
		printf("Invalid user0, repair...\n");
		uint8_t *user0_bak_p = (uint8_t *)(buf + USER0_OFFSET + HALF_TAG_SIZE - SEGMENT_SIZE);
		ret = write_segment_to_file(tag_fd, USER0_OFFSET, user0_bak_p, SEGMENT_SIZE);
		if (ret < 0) {
			printf("failed to write user0 to tag file\n");
			ret = -1;
			goto close_file;
		}
		repair++;
	}

	ret = 0;
	if (repair)
		printf("recover %d segment\n", repair);
	else
		printf("tag is ok\n");
//	dump_tag(path);

close_file:
	close(tag_fd);
free_buf:
	free(buf);
	return ret;
}

static int tag_ctrl(TAG_ACTION_INFO_S *pstActionInfo)
{
	int ret = 0;

	if (strlen(pstActionInfo->tagPath) == 0) {
		printf("please set <tag_path>\n");
		return -1;
	}

	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_DUMP) {
		if (access(pstActionInfo->tagPath, R_OK) != 0) {
			printf("%s can't be read\n", pstActionInfo->tagPath);
			return -1;
		}
		return dump_tag(pstActionInfo->tagPath);
	}

	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_RECOVERY) {
		if (access(pstActionInfo->tagPath, R_OK) != 0) {
			printf("%s can't be read\n", pstActionInfo->tagPath);
			return -1;
		}
		ret = recover_tag(pstActionInfo->tagPath);
		if (ret < 0)
			printf("recover tag failed\n");
		return ret;
	}

	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE) {
		if (file_create_ok(pstActionInfo->tagPath) != 0) {
			printf("%s can't be created\n", pstActionInfo->tagPath);
			return -1;
		}
	}

	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE) {
		if (access(pstActionInfo->tagPath, R_OK | W_OK) != 0) {
			printf("%s can't be accessed\n", pstActionInfo->tagPath);
			return -1;
		}
	}

	printf("Show arguments:\n");
	printf("  create=%s\n", pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE ? "true" : "false");
	printf("  update=%s\n", pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE ? "true" : "false");
	printf("  tag_path=%s\n", pstActionInfo->tagPath);
	printf("  env=%s\n", pstActionInfo->pEnv);
	printf("  boardinfo=%s\n", pstActionInfo->pBoardInfo);
	printf("  user0=%s\n", pstActionInfo->pUser0);
	
	uint8_t *wr_buf = (uint8_t *)malloc(MAX_TAG_SIZE);
	if (wr_buf == NULL) {
		printf("malloc tag buffer failed:%s\n", strerror(errno));
		return -1;
	}
	memset(wr_buf, 0xff, MAX_TAG_SIZE);

	uint8_t *segment_buf;
	segment_buf = (uint8_t *)malloc(SEGMENT_SIZE);
	if (segment_buf == NULL) {
		printf("malloc segment_buf failed:%s\n", strerror(errno));
		ret = -1;
		goto free_buf;
	}

	int tag_fd = 0, tag_len = 0;

	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE) {
		tag_fd = open(pstActionInfo->tagPath, O_CREAT | O_TRUNC | O_RDWR, 0644);
		if (tag_fd < 0) {
			printf("%s can't be create: %s\n", pstActionInfo->tagPath, strerror(errno));
			ret = -1;
			goto free_buf2;
		}

		tag_len = TAG_SIZE;

		/* write the head and thed end */
		*(uint32_t *)wr_buf = TAG_HEAD;
		*(uint32_t *)(wr_buf + TAG_SIZE - 4) = TAG_END;

	} else if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE) {
		tag_fd = open(pstActionInfo->tagPath, O_RDWR);
		if (tag_fd < 0) {
			printf("%s can't be read/write: %s\n", pstActionInfo->tagPath, strerror(errno));
			ret = -1;
			goto free_buf2;
		}

		tag_len = read(tag_fd, wr_buf, MAX_TAG_SIZE);
		if (tag_len < 0) {
			printf("read tag file failed:%s\n", strerror(errno));
			ret = -1;
			goto close_file;
		} else if (tag_len == 0) {
			printf("empty tag file\n");
			ret = -1;
			goto close_file;
		} else if (tag_len != TAG_SIZE) {
			printf("invalid tag size:%d\n", tag_len);
			ret = -1;
			goto close_file;
		}

		/* verify valid tag or not */
		if (*(uint32_t *)wr_buf != TAG_HEAD) {
			printf("invalid tag head\n");
			ret = -1;
			goto close_file;
		}

		if (*(uint32_t *)(wr_buf + TAG_SIZE - 4) != TAG_END) {
			printf("invalid tag end\n");
			ret = -1;
			goto close_file;
		}
	}
    
	/* env */
	if (pstActionInfo->pEnv != NULL && strlen(pstActionInfo->pEnv) != 0) {
		uint8_t *env_p = segment_buf;
		memset((void *)(env_p), 0xff, SEGMENT_SIZE);

		env_p[0] = 'E';
		env_p[1] = 'N';
		env_p[2] = 'V';
		env_p[3] = 'I';
		strcpy((void *)(env_p + MAX_HEAD_SIZE), pstActionInfo->pEnv);

		if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE)
			ret = write_segment_to_buffer(wr_buf + ENV_OFFSET, env_p, SEGMENT_SIZE);
		else if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE)
			ret = write_segment_to_file(tag_fd, ENV_OFFSET, env_p, SEGMENT_SIZE);

		if (ret < 0) {
			printf("failed to write env to tag file\n");
			goto close_file;
		}
	}
	/* env end */
	
	/* boardinfo */
	if (pstActionInfo->pBoardInfo != NULL && strlen(pstActionInfo->pBoardInfo) != 0) {
		uint8_t *boardinfo_p = segment_buf;
		memset((void *)(boardinfo_p), 0xff, SEGMENT_SIZE);

		boardinfo_p[0] = 'B';
		boardinfo_p[1] = 'D';
		boardinfo_p[2] = 'I';
		boardinfo_p[3] = 'F';
		strcpy((void *)(boardinfo_p + MAX_HEAD_SIZE), pstActionInfo->pBoardInfo);

		if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE)
			ret = write_segment_to_buffer(wr_buf + BOARDINFO_OFFSET, boardinfo_p, SEGMENT_SIZE);
		else if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE)
			ret = write_segment_to_file(tag_fd, BOARDINFO_OFFSET, boardinfo_p, SEGMENT_SIZE);

		if (ret < 0) {
			printf("failed to write boardinfo to tag file\n");
			goto close_file;
		}
	}
	/* boardinfo end */

	/* user0 */
	if (pstActionInfo->pUser0 != NULL && strlen(pstActionInfo->pUser0) != 0) {
		uint8_t *user0_p = segment_buf;
		memset((void *)(user0_p), 0xff, SEGMENT_SIZE);

		user0_p[0] = 'U';
		user0_p[1] = 'S';
		user0_p[2] = 'R';
		user0_p[3] = '0';
		strcpy((void *)(user0_p + MAX_HEAD_SIZE), pstActionInfo->pUser0);

		if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE)
			ret = write_segment_to_buffer(wr_buf + USER0_OFFSET, user0_p, SEGMENT_SIZE);
		else if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE)
			ret = write_segment_to_file(tag_fd, USER0_OFFSET, user0_p, SEGMENT_SIZE);

		if (ret < 0) {
			printf("failed to write user0 to tag file\n");
			goto close_file;
		}
	}
	/* user0 end */
    
	if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE || pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE) 
	{
		/* tag bak */
		memcpy(wr_buf + HALF_TAG_SIZE, wr_buf + TAG_INFO_SIZE, HALF_TAG_SIZE - SEGMENT_SIZE);
		/* tag bak end*/

		if (pstActionInfo->enActionType == TAG_ACTION_TYPE_UPDATE) {
		    lseek(tag_fd, HALF_TAG_SIZE, SEEK_SET);
    		ret = write(tag_fd, wr_buf + HALF_TAG_SIZE, HALF_TAG_SIZE - SEGMENT_SIZE);
    		if (ret != (HALF_TAG_SIZE - SEGMENT_SIZE)) {
    			printf("1write tag faled\n");
    		}		    
		} else if (pstActionInfo->enActionType == TAG_ACTION_TYPE_CREATE) {
    		lseek(tag_fd, 0, SEEK_SET);	
    		ret = write(tag_fd, wr_buf, tag_len);
    		if (ret != tag_len) {
    			printf("write tag faled\n");
    		}
		}
	}

close_file:
	close(tag_fd);
free_buf2:
	free(segment_buf);
free_buf:
	free(wr_buf);

    return ret;
}
static int read_tag_value(TAG_SEGMENT_INFO_S *pstSegmentInfo)
{
	int ret = 0;
	uint8_t *wr_buf = (uint8_t *)malloc(MAX_TAG_SIZE);
	if (wr_buf == NULL) {
		printf("malloc tag buffer failed:%s\n", strerror(errno));
		return -1;
	}
	memset(wr_buf, 0xff, MAX_TAG_SIZE);

	int tag_fd = open(pstSegmentInfo->tagPath, O_RDONLY);
	if (tag_fd < 0) {
		printf("%s can't be read: %s\n", pstSegmentInfo->tagPath, strerror(errno));
		ret = -1;
		goto free_buf;
	}

	int tag_len = read(tag_fd, wr_buf, MAX_TAG_SIZE);
	if (tag_len < 0) {
		printf("read tag file failed:%s\n", strerror(errno));
		ret = -1;
		goto close_file;
	} else if (tag_len == 0) {
		printf("empty tag file\n");
		ret = -1;
		goto close_file;
	} else if (tag_len != TAG_SIZE) {
		printf("invalid tag size:%d\n", tag_len);
		ret = -1;
		goto close_file;
	}

	/* verify valid tag or not */
	if (*(uint32_t *)wr_buf != TAG_HEAD) {
		printf("invalid tag head\n");
		ret = -1;
		goto close_file;
	}

	if (*(uint32_t *)(wr_buf + TAG_SIZE - 4) != TAG_END) {
		printf("invalid tag end\n");
		ret = -1;
		goto close_file;
	}

	uint8_t *segmentInfo_p = NULL;
	uint32_t *segmentInfo_head_p = NULL;
	
    switch (pstSegmentInfo->enSegmentType)
    {
        case TAG_SEGMENT_TYPE_ENV:
            segmentInfo_p = wr_buf + ENV_OFFSET;
            segmentInfo_head_p = (uint32_t *)&g_env_head;
            break;
        case TAG_SEGMENT_TYPE_BOARDINFO:
            segmentInfo_p = wr_buf + BOARDINFO_OFFSET;
            segmentInfo_head_p = (uint32_t *)&g_boardinfo_head;
            break;
        case TAG_SEGMENT_TYPE_USER0:
            segmentInfo_p = wr_buf + USER0_OFFSET;
            segmentInfo_head_p = (uint32_t *)&g_user0_head;
            break;
        case TAG_SEGMENT_TYPE_USER0_BAK:
            segmentInfo_p = wr_buf + USER0_OFFSET + (HALF_TAG_SIZE - SEGMENT_SIZE);
            segmentInfo_head_p = (uint32_t *)&g_user0_head;
            break;            
        default:
            break;
    }
    
	if (*(uint32_t *)segmentInfo_p != *segmentInfo_head_p) {
		printf("Invalid segment info\n");
		ret = -1;
		goto close_file;
	}

	strncpy(pstSegmentInfo->pValue, (char *)segmentInfo_p + MAX_HEAD_SIZE, pstSegmentInfo->maxSize - 1);

close_file:
    close(tag_fd);
free_buf:
	free(wr_buf);
	return ret;
}

int TagCreate(char *tagfile, char *env, char *boardinfo, char *user0)
{
    int ret = 0;
    TAG_ACTION_INFO_S stActionInfo;

    memset(&stActionInfo, 0, sizeof(stActionInfo));
    stActionInfo.enActionType = TAG_ACTION_TYPE_CREATE;
    stActionInfo.tagPath = tagfile;
    stActionInfo.pEnv = env;
    stActionInfo.pBoardInfo = boardinfo;
   	stActionInfo.pUser0 = user0;

    ret = tag_ctrl(&stActionInfo);

    return ret;
}

int TagUpdate(char *tagfile, char *env, char *boardinfo, char *user0)
{
    int ret = 0;
    TAG_ACTION_INFO_S stActionInfo;

    memset(&stActionInfo, 0, sizeof(stActionInfo));
    stActionInfo.enActionType = TAG_ACTION_TYPE_UPDATE;
    stActionInfo.tagPath = tagfile;
    stActionInfo.pEnv = env;
    stActionInfo.pBoardInfo = boardinfo;
	stActionInfo.pUser0 = user0;
    
    ret = tag_ctrl(&stActionInfo);

    return ret;
}

int TagGetValue(char *tagfile, TAG_SEGMENT_TYPE_E enType, char *pValue, int maxSize)
{
	int ret = 0;
    TAG_SEGMENT_INFO_S stSegmentInfo;
	
	memset(&stSegmentInfo, 0, sizeof(stSegmentInfo));
	stSegmentInfo.enSegmentType = enType;
	stSegmentInfo.tagPath = tagfile;
	stSegmentInfo.maxSize = maxSize;
	stSegmentInfo.pValue = pValue;
	ret = read_tag_value(&stSegmentInfo);

	return ret;
}

int TagRecovery(char *tagfile)
{
    int ret = 0;
    TAG_ACTION_INFO_S stActionInfo;

    memset(&stActionInfo, 0, sizeof(stActionInfo));
    stActionInfo.enActionType = TAG_ACTION_TYPE_RECOVERY;
    stActionInfo.tagPath = tagfile;
    
    ret = tag_ctrl(&stActionInfo);

    return ret;
}

int TagDump(char *tagfile)
{
    int ret = 0;
    TAG_ACTION_INFO_S stActionInfo;

    memset(&stActionInfo, 0, sizeof(stActionInfo));
    stActionInfo.enActionType = TAG_ACTION_TYPE_DUMP;
    stActionInfo.tagPath = tagfile;
    
    ret = tag_ctrl(&stActionInfo);

    return ret;   
}

#if 0
int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("Usage: \n\t%s [create/update/recovery/dump/get] [env/boardinfo/user0]\n\n", argv[0]);
        return -1;
    }
    
    char env[] = "senv;[SW];version=V1.12;init_vw=640;init_vh=360;[FAC];UUID=xxxx;[WIFI];SSID=xxxx;PASS=xxx;eenv;";
    char boardinfo[] = "sboard;[PRODUCT];MODLE=B1;CHIP=HI3518EV300;HWVER=B1-MAIN-V10;CLIENT=CN;[DRIVER];SENSORTYPE=PS5260;WIFITYPE=HI1131;BOOLAUDIO=1;BOOLMOTOR=1;BOOLUVC=1;BOOL4G=1;eboard";
	char user0[4096] = "";

    if (strcmp("create", argv[1]) == 0)
    {
		TagCreate("tag1.bin", env, boardinfo, user0);
    }
    else if (strcmp("update", argv[1]) == 0)
    {
        TagUpdate("tag1.bin", "112233", "aabbcc", NULL);
    }
    else if (strcmp("recovery", argv[1]) == 0)
    {
        TagRecovery("tag1.bin");
    }
    else if (strcmp("dump", argv[1]) == 0)
    {
        TagDump("tag1.bin");
    }
    else if (strcmp("get", argv[1]) == 0)
    {
        if (argc != 3) {
            printf("input [env/boradinfo]\n");
            return -1;
        }

        char result[1024] = "";
        if (strcmp("env", argv[2]) == 0)
        {
			TagGetValue("tag1.bin", TAG_SEGMENT_TYPE_ENV, result, sizeof(result));
        }
        else if (strcmp("boardinfo", argv[2]) == 0)
        {
			TagGetValue("tag1.bin", TAG_SEGMENT_TYPE_BOARDINFO, result, sizeof(result));
        }
        else if (strcmp("user0", argv[2]) == 0)
		{
			TagGetValue("tag1.bin", TAG_SEGMENT_TYPE_USER0, result, sizeof(result));
		}
		printf("%s: %s\n", argv[2], result);
    }    
    else 
    {
        printf("invalid params!\n");
    }

    return 0;
}
#endif
